package com.starry.security.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.starry.security.entity.SecurityUser;
import com.starry.security.entity.User;
import com.starry.security.security.TokenManager;
import com.starry.utils.utils.R;
import com.starry.utils.utils.ResponseUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

//授权过滤器
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {

	private TokenManager tokenManager;
	private RedisTemplate redisTemplate;
	private AuthenticationManager authenticationManager;


	public TokenLoginFilter(AuthenticationManager authenticationManager, RedisTemplate redisTemplate, TokenManager tokenManager) {
		this.authenticationManager = authenticationManager;
		this.redisTemplate = redisTemplate;
		this.tokenManager = tokenManager;
		this.setPostOnly(false);
		this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/admin/acl/login", "POST"));
	}

	//1.获取表单提交的用户名和密码
	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
		//先获取表单提交的数据
		try {
			User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
			return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), AuthorityUtils.createAuthorityList()));
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException();
		}
	}

	//2.认证成功
	@Override
	protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
		//认证成功之后用户的信息
		SecurityUser user = (SecurityUser) authResult.getPrincipal();
		//根据用户名生成token
		String token = tokenManager.createToken(user.getCurrentUserInfo().getUsername());
		//放入redis
		redisTemplate.opsForValue().set(user.getCurrentUserInfo().getUsername(), user.getPermissionValueList());
		ResponseUtil.out(response, R.ok().data("token", token));
	}

	//3.认证失败
	@Override
	protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed)
			throws IOException, ServletException {
		ResponseUtil.out(response, R.error());
	}
}
